Skip to content

feat(runtime-host): add managed update reconciliation - #3720

Merged
M4n5ter merged 5 commits into
apache:mainfrom
M4n5ter:feat/runtime-host-update-reconciliation
Aug 25, 2026
Merged

feat(runtime-host): add managed update reconciliation#3720
M4n5ter merged 5 commits into
apache:mainfrom
M4n5ter:feat/runtime-host-update-reconciliation

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 24, 2026

Copy link
Copy Markdown
Member
English

Summary

  • persist one installation-scoped manual | fixed | latest | next update policy, with state-free manual as the default
  • keep automatic update authority inside the managed deployment so uninstall and deployment cleanup revoke it together
  • resolve each policy snapshot to one exact version and verified package identity before delegating to the existing update transaction
  • serialize policy changes, reconciliation, and uninstall through the existing deployment authority; validate the selected target before revocation
  • expose bounded machine outcomes for current, changed, active-work, manual-action, retry, and uncertain policy commits without adding a scheduler or updater daemon

The current deployment is reused when it is already selected, avoiding an unnecessary package download on no-op reconciliation.

Fixes #3717

Refs #3228
Refs #3709

Verification

  • npm run format:check
  • npm run lint
  • npm run typecheck
  • npm run check:asf-headers
  • npm --workspace packages/cli run test:dist — 450 passed
  • exercised the compiled CLI with a fresh Client Data Root and confirmed that policy defaults to manual and reconciliation returns disabled

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex implemented and tested the change under maintainer direction. Human review is still required before this Draft becomes ready.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
简体中文

摘要

  • 持久化 installation-scoped 的互斥策略 manual | fixed | latest | next,默认 manual 且不保存冗余状态
  • 将自动更新 authority 保存在 managed deployment 内,使 uninstall 与 deployment cleanup 一并撤销它
  • 在调用现有 update transaction 前,将每份 policy snapshot 解析为精确版本与已验证的 package identity
  • 由现有 deployment authority 序列化策略变更、reconciliation 与 uninstall,并在撤销 authority 前验证所选 target
  • 提供有界机器契约,区分 current、changed、active work、manual action、retry 与 policy commit outcome unknown,不引入 scheduler 或 updater daemon

目标已是当前 deployment 时直接复用它,避免 no-op reconciliation 重复下载 package。

修复 #3717

关联 #3228
关联 #3709

验证

  • npm run format:check
  • npm run lint
  • npm run typecheck
  • npm run check:asf-headers
  • npm --workspace packages/cli run test:dist — 450 项通过
  • 使用全新 Client Data Root 运行编译后的 CLI,确认策略默认是 manual,reconciliation 返回 disabled

依赖

AI 使用

OpenAI Codex 在维护者指导下实现并测试了本次变更;Draft 转为 Ready 前仍需要人工审查。

Checklist

  • 测试覆盖新增行为,并能在缺少实现时失败
  • lint、format、typecheck 与受影响测试均已在本地通过
  • 本 PR 会改变行为,具体见上方摘要

@me2seeks me2seeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the 4d8efd8 reconciliation layer on top of #3687. The core shape is clean: state-free manual, one policy snapshot under a reconciliation lock, delegation to the verified selected-update transaction, and no second scheduler/updater state machine. I found two recovery-contract gaps in the inline comments below.

One scope/wording boundary: the persisted record is currently bound to clientDataRoot plus {serviceId, rootPath, rootId}. That is a useful exact managed-service target fence, but it is not yet the positive durable local-owner identity and transfer protocol tracked by #3709. This PR does not need to solve #3709; describing the current result as managed-service-target-bound or installation-scoped would avoid implying that the local owner gate is already closed.

简体中文

我按 #3687 之上的增量审查了 4d8efd8。整体形状很干净:manual 不保存冗余状态、reconciliation lock 内只读取一次 policy snapshot、复用已验证的 selected-update transaction,并且没有创建第二套 scheduler/updater 状态机。下面两条行内评论是仍需闭合的恢复契约问题。

另有一个范围与术语边界:当前持久记录实际绑定的是 clientDataRoot{serviceId, rootPath, rootId}。这能为 managed service 提供精确 target fence,但还不是 #3709 所跟踪的 durable local owner 正向身份与 transfer protocol。本 PR 不需要顺手解决 #3709;将当前能力表述为 managed-service target binding 或 installation-scoped,可以避免让人误以为 local owner gate 已经闭合。

Comment thread packages/cli/src/runtime-host-update-policy-store.ts Outdated
Comment thread packages/runtime-host/src/operator/service-management-frame.ts Outdated
@M4n5ter
M4n5ter force-pushed the feat/runtime-host-update-reconciliation branch from 4d8efd8 to c819f54 Compare August 24, 2026 14:38
@M4n5ter

M4n5ter commented Aug 24, 2026

Copy link
Copy Markdown
Member Author

@me2seeks

English

Thanks for the scope distinction. I changed the PR wording from owner-bound to installation-scoped; this PR does not claim the durable local-owner identity or transfer protocol tracked by #3709.

I did not retain the separate reconciliation lock after tracing its actual authority. It covered policy resolution and network work without making the full operation atomic, while duplicating the deployment transaction's concurrency boundary. Policy mutations and uninstall now use the existing deployment lock; reconciliation reads one atomic policy snapshot and delegates the exact {version, integrity} deployment to the existing transaction. This keeps one mutation authority without introducing a third lock domain.

The same pass also fixed two independent contract gaps: JSON reconciliation now emits exactly one terminal JSON document, and uninstall revokes automatic policy before destructive lifecycle work.

简体中文

感谢指出范围差异。我已将 PR 中的 owner-bound 改为 installation-scoped;本 PR 不宣称已经实现 #3709 跟踪的 durable local-owner identity 或 transfer protocol。

在追踪实际 authority 后,我没有保留独立的 reconciliation lock。它覆盖了 policy 解析与网络工作,却不能让完整操作具备原子性,同时又重复了 deployment transaction 的并发边界。现在 policy mutation 与 uninstall 复用现有 deployment lock;reconciliation 读取一份原子 policy snapshot,再把精确的 {version, integrity} deployment 交给现有 transaction。这样只保留一个 mutation authority,不新增第三个锁域。

同一轮还修复了两个独立契约缺口:JSON reconciliation 现在只输出一个 terminal JSON document;uninstall 会在破坏性 lifecycle 操作前撤销自动更新 policy。

Comment thread packages/cli/src/runtime-host-update-reconciliation.ts Outdated
Persist one owner-bound update policy and resolve it to an exact, verified deployment before delegating to the existing update transaction. Keep manual mode state-free, serialize policy changes with reconciliation and uninstall, and expose bounded machine outcomes for future schedulers and clients.

Generated-by: Codex
Make policy removal crash-durable and revoke unattended update authority before destructive uninstall work begins. Reuse the deployment lock for policy mutations and route update frames through one sink so JSON reconciliation emits one terminal document.

Generated-by: Codex
Revalidate the selected managed-update policy inside the deployment lock before reading or mutating service state. This lets a newer manual or fixed policy revoke an in-flight unattended reconciliation without introducing another lock or scheduler state machine.

Generated-by: Codex
Store automatic update authority with the managed deployment so uninstall and legacy cleanup remove it together. Validate the selected target before revocation, preserve truthful commit uncertainty, and keep reconciliation on one output and equality path.

Generated-by: Codex
@M4n5ter
M4n5ter force-pushed the feat/runtime-host-update-reconciliation branch from edde381 to d0ac9d0 Compare August 25, 2026 02:24
@M4n5ter
M4n5ter marked this pull request as ready for review August 25, 2026 02:34

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this head and found no blocking issues.

Managed update policy adds atomic file-backed policy store with optimistic revalidation, correctly handling concurrent modifications, persistence failures, and schema validation. No concurrency or authority gaps beyond a minor maintainability note.

Minor note: adds moderate new surface (4 files + frame extensions) for declarative update management — valuable for hosted operations, well isolated, no daemon required.

Checks on d0ac9d0683 are pending — code side GO.

简体中文该头未发现阻断,增熵可接受。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this head and found a blocking issue.

[P2] Corrupt config + external uninstall leaves update authority alive

runtime-host-service-manager.ts:403-407 looks for the managed deployment via parsed config or current cliPath. When the service config is corrupt, the first is null; the documented npx ... service uninstall from an external CLI is not in the managed deployment, so the second is also undefined. Uninstall still succeeds without revoking the automatic latest/fixed policy. Reinstall then reuses the deterministic deployment root and the old policy is immediately valid again.

Repro uses real storage root ID with an external CLI path: policy survives uninstall, reinstall target validation passes.

Fix: fail closed when the deployment cannot be located due to invalid config, or keep an authoritative deployment identity outside the corruptible config; cover external-CLI corrupt-config uninstall → reinstall.

Checks on d0ac9d0683 are test: success.

简体中文损坏配置+外部卸载后自动更新权限未回收,需闭合。

Treat automatic update policy revocation as a separate uninstall authority from deleting the managed deployment. A safely validated deterministic deployment can revoke policy when service configuration is corrupt, while destructive cleanup still requires stronger ownership evidence.\n\nGenerated-by: Codex
@M4n5ter

M4n5ter commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@Astro-Han

English

Confirmed and fixed in 3c8b08278.

The fix separates two authorities that uninstall previously conflated:

  • automatic update policy may be revoked from the installation's safely validated deterministic deployment root when a corrupt config and an external CLI leave no configured root;
  • deleting the whole deployment still requires the stronger existing evidence from valid config or a CLI that belongs to that deployment.

The deterministic fallback is inspected as a real, non-redirected directory before policy mutation. If the config is corrupt and revocation cannot be confirmed, uninstall now fails closed before stopping the service. The regression covers corrupt config + external CLI uninstall + reinstall and verifies that the old automatic policy cannot revive.

The CLI suite passes with 450 tests, together with format, lint, typecheck, and ASF header checks.

简体中文

已确认并在 3c8b08278 中修复。

修复将 uninstall 之前混在一起的两种 authority 分开:

  • config 损坏且命令来自外部 CLI 时,可以通过 installation 经过安全验证的 deterministic deployment root 撤销自动更新策略;
  • 删除整个 deployment 仍然要求原有的更强证据,即有效 config 或确实属于该 deployment 的 CLI。

在修改 policy 前,deterministic fallback 必须被验证为真实、未重定向的目录。若 config 已损坏且无法确认策略已撤销,uninstall 会在停止 service 前 fail closed。回归测试覆盖了“损坏 config + 外部 CLI uninstall + reinstall”,并确认旧自动更新策略不会复活。

CLI 450 项测试以及 format、lint、typecheck 和 ASF header 检查均已通过。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on 3c8b08278c:

The previous P2 (corrupt config + external CLI uninstall leaving policy alive) is now closed. The manager now resolves the deterministic deployment root, validates it, revokes the policy, and fail-closes if the deployment cannot be confirmed before backend uninstall. External-CLI + reinstall is now covered and the old policy no longer resurrects.

No remaining P0-P2. Minor maintainability note remains non-blocking.

Checks on 3c8b08278c are test: success.

简体中文该阻断已在该头闭合。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE — 3c8b082, P2 closed, test success.

@M4n5ter
M4n5ter merged commit 183090d into apache:main Aug 25, 2026
1 check passed
@M4n5ter
M4n5ter deleted the feat/runtime-host-update-reconciliation branch August 25, 2026 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(runtime-host): add managed update reconciliation policy

3 participants